# coding=utf8
'''
by vista @ 20170620 
'''
import loaders.loader as ml
import tensorflow as tf

mnist = ml.get_mnist_set(True)

sess = tf.InteractiveSession()

# input
x = tf.placeholder("float", shape=[None, 784])

# output
y_ = tf.placeholder("float", shape=[None, 10])

# hidden nodes

hnsize = 1024


def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev = 0.01))


def model(X, w_layer_1, b1, w_layer_2, b2, p_keep_input, p_keep_hidden):

    X = tf.nn.dropout(X, p_keep_input)

    hidden_1 = tf.nn.relu(tf.matmul(X, w_layer_1)+b1)

    hidden_1 = tf.nn.dropout(hidden_1, p_keep_hidden)

    # return tf_vista.matmul(hidden_1, w_layer_2) + b2
    return  tf.nn.softmax( tf.matmul( hidden_1, w_layer_2 ) + b2 )

# 在该模型中我们一共有3层，一个输入层，一个隐藏层，一个输出层
# 定义输入层到第一个隐藏层之间的连接矩阵
# first connection

W1 = init_weights([784,hnsize])

b1 = tf.Variable(tf.zeros([hnsize]))

W2 = init_weights([hnsize,10])

b2 = tf.Variable(tf.zeros([10]))

# dropout 系数
# 定义有多少有效的神经元将作为输入神经元，比如 p_keep_intput = 0.8，那么只有80%的神经元将作为输入
p_keep_input = tf.placeholder("float")

# 定义有多少的有效神经元将在隐藏层被激活
p_keep_hidden = tf.placeholder("float")

py_x = model(x,W1,b1,W2,b2,p_keep_input,p_keep_hidden)

"""
xout = tf_vista.nn.dropout(x, p_keep_input)
# !can not use this..
# y1 = tf_vista.nn.softmax(tf_vista.matmul(xout,W1) + b1)
y1 = tf_vista.nn.relu(tf_vista.matmul(xout,W1) + b1)
y1out = tf_vista.nn.dropout(y1, p_keep_hidden)
py_x = tf_vista.matmul(y1out,W2) + b2

"""

#
cross_entropy = -tf.reduce_sum(y_*tf.log(py_x))

#cross_entropy = tf_vista.reduce_mean(tf_vista.nn.softmax_cross_entropy_with_logits( logits = py_x, labels = y_))

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

correct_prediction = tf.equal(tf.argmax(py_x ,1), tf.argmax(y_,1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

sess.run(tf.global_variables_initializer())

saver = tf.train.Saver(tf.global_variables())

for i in range(10000):
    batch = mnist.train.next_batch(50)
    if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={
            x:batch[0], y_: batch[1],p_keep_input: 1.0, p_keep_hidden: 1.0})
        print "step %d, training accuracy %g"%(i, train_accuracy)
    train_step.run(feed_dict={x: batch[0], y_: batch[1], p_keep_input : 0.8, p_keep_hidden : 0.5})


model_dir = '/Users/vista/PycharmProjects/data/model/mnist_1hidden/'
saver.save(sess, model_dir + 'm')
# if os.path.exists(model_dir + 'm.index'):
#     saver.restore(sess, model_dir + 'm')

print accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, p_keep_input: 1.0, p_keep_hidden: 1.0})
